const sqlite3 = require('@journeyapps/sqlcipher')

/**
 * SQLCipher适配器，用于与Knex.js配合使用
 * 提供加密SQLite数据库的完整支持
 */
class SQLCipherAdapter {
  constructor() {
    // 标识这是一个自定义适配器
    this.driverName = 'sqlcipher'
  }

  /**
   * 创建Knex客户端
   */
  createClient(config) {
    // 使用sqlite3基础客户端但替换数据库驱动
    const Client = require('knex/lib/dialects/sqlite3/index.js')

    class SQLCipherClient extends Client {
      constructor(config) {
        super(config)
        this.driverName = 'sqlcipher'
        this.config = config
      }

      // 重写driver方法以使用SQLCipher
      get driver() {
        return sqlite3
      }
      
      // 重写初始化驱动方法
      initializeDriver() {
        // 不调用父类的初始化，直接设置我们的驱动
        this._driver = sqlite3
      }

      // 重写连接获取方法
      acquireRawConnection() {
        return new Promise((resolve, reject) => {
          const connectionConfig = this.connectionSettings
          console.log('SQLCipherAdapter: 创建加密数据库连接...', {
            filename: connectionConfig.filename,
            hasKey: !!connectionConfig.key,
            keyLength: connectionConfig.key ? connectionConfig.key.length : 0
          })
          
          const db = new sqlite3.Database(connectionConfig.filename, (openErr) => {
            if (openErr) {
              console.error('SQLCipherAdapter: 数据库文件打开失败:', openErr)
              reject(openErr)
              return
            }

            // 设置加密密钥
            if (connectionConfig.key) {
              db.run(`PRAGMA key = '${connectionConfig.key}'`, (keyErr) => {
                if (keyErr) {
                  console.error('SQLCipherAdapter: 设置SQLCipher密钥失败:', keyErr)
                  reject(keyErr)
                  return
                }

                // 设置其他SQLCipher选项
                const pragmas = [
                  'PRAGMA cipher_compatibility = 4',
                  'PRAGMA cipher_page_size = 4096',
                  'PRAGMA kdf_iter = 256000',
                  'PRAGMA cipher_hmac_algorithm = HMAC_SHA512',
                  'PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512'
                ]
                
                let pragmaCount = 0
                let pragmaErrors = []
                
                const setPragma = (pragmaSQL) => {
                  return new Promise((pragmaResolve) => {
                    db.run(pragmaSQL, (pragmaErr) => {
                      if (pragmaErr) {
                        console.warn(`SQLCipherAdapter: 设置PRAGMA失败 (${pragmaSQL}):`, pragmaErr.message)
                        pragmaErrors.push(pragmaErr)
                      } else {
                        console.log(`SQLCipherAdapter: 成功设置 ${pragmaSQL}`)
                      }
                      pragmaResolve()
                    })
                  })
                }
                
                // 串行设置所有 PRAGMA
                Promise.all(pragmas.map(setPragma)).then(() => {
                  // 测试连接
                  db.get('SELECT 1 as test', (testErr, row) => {
                    if (testErr) {
                      console.error('SQLCipherAdapter: 连接测试失败:', testErr)
                      reject(testErr)
                    } else {
                      console.log('SQLCipherAdapter: SQLCipher数据库连接成功')
                      if (pragmaErrors.length > 0) {
                        console.warn(`SQLCipherAdapter: ${pragmaErrors.length}个PRAGMA设置有警告，但连接成功`)
                      }
                      resolve(db)
                    }
                  })
                })
              })
            } else {
              reject(new Error('SQLCipherAdapter: SQLCipher需要提供加密密钥'))
            }
          })
        })
      }

      // 重写连接销毁方法
      destroyRawConnection(connection) {
        return new Promise((resolve) => {
          try {
            connection.close((error) => {
              if (error) {
                console.warn('关闭SQLCipher连接时出错:', error.message)
              }
              resolve()
            })
          } catch (error) {
            console.warn('销毁SQLCipher连接时出错:', error.message)
            resolve()
          }
        })
      }

      // 连接验证
      validateConnection(connection) {
        return new Promise((resolve) => {
          connection.get('SELECT 1', (error) => {
            resolve(!error)
          })
        })
      }
    }

    return new SQLCipherClient(config)
  }
}

module.exports = SQLCipherAdapter